package com.etone.smartAudit.utils;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author: sovy
 * @date: 2020/11/25
 * @description:
 */
@Component
public class SignUtil {

    public static String SIGN_KEY;

    @Value(value = "${serverFileOperation.key}")
    public void setSignKey(String signKey) {
        SIGN_KEY = signKey;
    }

    /**
     * 对象签名
     *
     * @param obj
     * @param timestamp
     * @return
     */
    public static String sign(Object obj, Long timestamp) {
        Map<String, Object> stringObjectMap;
        if (ObjectUtil.isBaseType(obj)) {
            stringObjectMap = new HashMap<>();
            stringObjectMap.put(String.valueOf(obj), obj);
        } else {
            stringObjectMap = ObjectUtil.toMap(obj);
        }

        stringObjectMap.put("timestamp", timestamp);
        return signMap(stringObjectMap);
    }

    /**
     * map签名
     *
     * @param params
     * @return
     */
    public static String sign(Map<String, Object> params) {
        return signMap(params);
    }

    /**
     * list签名
     *
     * @param lists
     * @param timestamp
     * @return
     */
    public static <T> String sign(List<T> lists, Long timestamp) {
        return signList(lists, timestamp);
    }

    /**
     * 签名对象
     *
     * @param params
     * @return
     */
    public static String signMap(Map<String, Object> params) {

        //键值排序
        List<String> keys = params.keySet().stream().filter(key -> key != null && !key.equals("sign")).sorted().collect(Collectors.toList());
        StringBuffer sb = new StringBuffer();
        keys.forEach(key -> {
            //值为null的参数不参与签名
            if (params.get(key) != null) {
                sb.append(key).append("=").append(params.get(key));
            }

        });

        //拼接签名秘钥
        sb.append(SIGN_KEY);

        //剔除参数中含有的'&'符号
        String signStr = sb.toString().replaceAll("&", "");
        return Md5Util.Md5(signStr).toLowerCase();
    }

    /**
     * 签名数组
     *
     * @param lists
     * @param timestamp
     * @param <T>
     * @return
     */
    public static <T> String signList(List<T> lists, Long timestamp) {
        StringBuffer sb = new StringBuffer();
        T t = lists.get(0);
        //判断是否是基本类型
        boolean isBaseType = ObjectUtil.isBaseType(t);
        if (isBaseType) {
            lists.stream().sorted().forEach(list -> {
                sb.append(list);
            });
        } else {
            lists.forEach(list -> {
                Map<String, Object> params = ObjectUtil.toMap(list);
                //键值排序
                List<String> keys = params.keySet().stream().filter(key -> key != null && !key.equals("sign")).sorted().collect(Collectors.toList());
                keys.forEach(key -> {
                    //值为null的参数不参与签名
                    if (params.get(key) != null) {
                        sb.append(key).append("=").append(params.get(key));
                    }
                });
            });
        }
        //拼接签名秘钥
        sb.append(timestamp).append(SIGN_KEY);

        //剔除参数中含有的'&'符号
        String signStr = sb.toString().replaceAll("&", "");
        return Md5Util.Md5(signStr).toLowerCase();
    }

}
